package com.can.forkJoin;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * 求和计算的任务
 * 3000   6000(ForkJoin)   9000(Stream并行流)
 * 如何使用ForkJoin：
 * 1.forkJoinPool 通过它来执行
 * 2.计算任务 forkJoinPool.execute(ForkJoinTask<?> task)
 * 3.计算类要继承ForkJoinTask（RecursiveTask）
 */
public class ForkJoinDemo01 extends RecursiveTask<Long> {

    private Long start; //1
    private Long end;   //1800088000

    //临界值
    private Long temp = 10000L;

    public ForkJoinDemo01(Long start, Long end) {
        this.start = start;
        this.end = end;
    }

    //    psvm
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //ForkJoin
        ForkJoinDemo01 entity = new ForkJoinDemo01(0L, 3L);
        ForkJoinTask<Long> fork = entity.fork();
        System.out.println(fork.get());
        //Stream流式计算
        int sum1 = IntStream.rangeClosed(0, 3).parallel().reduce(Integer::sum).getAsInt();
        System.out.println(sum1);
        int sum2 = IntStream.rangeClosed(0, 3).reduce(Integer::sum).getAsInt();
        System.out.println(sum2);
        //identity参数 则代表的每个都加的值
        //(0 + 1) + (1 + 1) + (2 + 1) + (3 + 1)=‬ 10
        int sum3 = IntStream.rangeClosed(0, 3).parallel().reduce(1,(a,b)->a+b);
        System.out.println(sum3);
        //只是用了lambda表达式，跟sum3没区别
        int sum4 = IntStream.rangeClosed(0, 3).parallel().reduce(1,Integer::sum);
        System.out.println(sum4);

        int sum5 = Stream.of(1,2,3).reduce(2,Integer::sum);
        //结果不同  是因为  ((((5+1)+2)+3)+4)+5   和   (5+1)+ (5+2)+ (5+3)+ (5+4)+ (5+5)  运算结果不相同
        //前者是sum5的转Stream流，而后则是除了sum5的parallel
        System.out.println(sum5);
    }

    //计算方法
    @Override
    protected Long compute() {
        if ((end - start) < temp) {
            //分支合并计算
            Long sum = 0L;
            for (Long i = start; i <= end; i++) {
                sum += i;
            }
            return sum;
        } else {    //ForkJoin  递归
            long middle = (start+end)/2; //中间值
            ForkJoinDemo01 task1 = new ForkJoinDemo01(start, middle);
            task1.fork(); //拆分任务，把任务压入线程队列
            ForkJoinDemo01 task2 = new ForkJoinDemo01(middle+1, end);
            task2.fork(); //拆分任务，把任务压入线程队列

            return task1.join() + task2.join();
        }

    }
}
